<template>
  <j-modal
    :title="title"
    :width="1200"
    :visible="visible"
    :maskClosable="false"
    :confirmLoading="confirmLoading"
    switchFullscreen
    @cancel="handleCancel"
  >
    <a-spin :spinning="confirmLoading">
      <!-- 主表单区域 -->
      <a-form :form="form">
        <j-form-container :disabled="formDisabled">
          <a-row slot="detail">
            <a-col :xs="24" :sm="12">
              <a-form-item label="报损单名称" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <a-input v-decorator="['scrapName', validatorRules.scrapName]" placeholder="请输入报损单名称"></a-input>
              </a-form-item>
            </a-col>
            <a-col :xs="24" :sm="12">
              <a-form-item label="调整仓库" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <j-popup
                  v-decorator="['storeId_dictText', validatorRules.storeId]"
                  :trigger-change="true"
                  org-fields="id,store_name"
                  dest-fields="storeId,storeId_dictText"
                  :list-data.sync="storeList"
                  code="store_info"
                  @callback="popupCallback"
                />
              </a-form-item>
              <a-form-item label="调整仓库ID" style="height: 0; overflow: hidden; margin-bottom: 0px">
                <a-input v-decorator="['storeId', validatorRules.storeId]"></a-input>
              </a-form-item>
            </a-col>
            <a-col :xs="24" :sm="12">
              <a-form-item label="报损总价" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <a-input-number v-decorator="['totalPrice']" disabled style="width: 100%" />
              </a-form-item>
            </a-col>
            <a-col :span="24">
              <a-form-item label="调整原因" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
                <a-textarea v-decorator="['scrapReason', validatorRules.scrapReason]" rows="4" />
              </a-form-item>
            </a-col>
          </a-row>
        </j-form-container>

        <a-row v-show="['审批', '详情'].includes(title)">
          <j-form-container :disabled="title !== '审批'">
            <a-col slot="detail" :span="24">
              <a-form-item label="审批备注" :labelCol="labelCol2" :wrapperCol="wrapperCol2">
                <a-textarea v-decorator="['remark']" rows="4" />
              </a-form-item>
            </a-col>
          </j-form-container>
        </a-row>
      </a-form>

      <!-- 子表单区域 -->
      <a-tabs v-model="activeKey" @change="handleChangeTabs">
        <a-tab-pane tab="报损单明细" :key="refKeys[0]" :forceRender="true">
          <j-editable-table
            :ref="refKeys[0]"
            :loading="stockScrapApprovalDetailTable.loading"
            :columns="stockScrapApprovalDetailTable.columns"
            :dataSource="stockScrapApprovalDetailTable.dataSource"
            :maxHeight="300"
            :rowNumber="true"
            :rowSelection="!formDisabled"
            :actionButton="!formDisabled"
            :disabled="formDisabled"
            @added="rowAdd"
            @deleted="rowDel"
          >
            <!-- 商品 -->
            <template #goodsIdSlot="slotProps">
              <a-select
                show-search
                :disabled="formDisabled"
                option-filter-prop="children"
                :filter-option="goodsFilterOption"
                allowClear
                @focus="goodsIdFocus(slotProps)"
                v-model="tabledata[slotProps.rowId].goodsId"
                @change="goodsIdChange(slotProps, $event)"
                style="width: 100%"
              >
                <a-select-option
                  :value="item.goodsId"
                  v-for="item in tabledata[slotProps.rowId].goodsIdList"
                  :key="item.goodsId"
                >
                  {{ item.goodsName }}
                </a-select-option>
              </a-select>
            </template>
            <!-- 规格 -->
            <template #goodsSpecSlot="slotProps">
              <a-select
                allowClear
                :disabled="formDisabled"
                @focus="goodsSpecFocus(slotProps)"
                v-model="tabledata[slotProps.rowId].goodsSpec"
                @change="goodsSpecChange(slotProps, $event)"
                style="width: 100%"
              >
                <a-select-option
                  :value="item.specsId"
                  v-for="item in tabledata[slotProps.rowId].goodsSpecList"
                  :key="item.specsId"
                >
                  {{ item.specsName + '；数量：' + item.num }}
                </a-select-option>
              </a-select>
            </template>
          </j-editable-table>
        </a-tab-pane>
      </a-tabs>
    </a-spin>
    <template slot="footer">
      <div v-show="title == '审批'">
        <a-button key="back" @click="handleApp(1)"> 驳回 </a-button>
        <a-button key="submit" type="primary" @click="handleApp(2)"> 通过 </a-button>
      </div>
      <div v-show="title == '详情'">
        <a-button key="back" @click="handleCancel"> 关闭 </a-button>
      </div>
      <div v-show="!formDisabled">
        <a-button key="back" @click="handleCancel"> 关闭 </a-button>
        <a-button key="submit" type="primary" @click="handleOk"> 确定 </a-button>
      </div>
    </template>
  </j-modal>
</template>

<script>
import pick from 'lodash.pick'
import { FormTypes, getRefPromise } from '@/utils/JEditableTableUtil'
import { JEditableTableMixin } from '@/mixins/JEditableTableMixin'
import { validateDuplicateValue } from '@/utils/util'
// api
import { getStockPosition, getQueryBySpaceId, getQueryByGoodsId, postStockScrapApproval } from '@/api/storeApproval'

/**
 *  tabledata 对象 key: rowId, item: 存储对象内容
 *  id           行id
 *  spaceId      报损仓位id
 *  goodsId      商品id
 *  goodsSpec    规格id
 *  price        价格
 *  scrapNum     数量
 *  totalPrice   报损总价
 */
export default {
  name: 'StockScrapApprovalModal',
  mixins: [JEditableTableMixin],
  components: {},
  data() {
    return {
      storeList: null,
      tabledata: null,
      disableSubmit: false,
      // ====================================
      labelCol: {
        xs: { span: 24 },
        sm: { span: 6 },
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
      },
      labelCol2: {
        xs: { span: 24 },
        sm: { span: 3 },
      },
      wrapperCol2: {
        xs: { span: 24 },
        sm: { span: 20 },
      },
      // 新增时子表默认添加几行空数据
      addDefaultRowNum: 0,
      validatorRules: {
        scrapName: {
          rules: [{ required: true, message: '请输入报损单名称!' }],
        },
        storeId: {
          rules: [{ required: true, message: '请选择调整仓库!' }],
        },
        totalPrice: {
          rules: [{ required: true, message: '请输入报损总价!' }],
        },
        scrapReason: {
          rules: [{ required: true, message: '请输入调整原因!' }],
        },
      },
      refKeys: ['stockScrapApprovalDetail'],
      tableKeys: ['stockScrapApprovalDetail'],
      activeKey: 'stockScrapApprovalDetail',
      // 报损单明细
      stockScrapApprovalDetailTable: {
        loading: false,
        dataSource: [],
        columns: [
          {
            title: '报损仓位',
            key: 'spaceId',
            type: FormTypes.sel_search,
            options: [],
            width: '200px',
            placeholder: '请选择${title}',
            defaultValue: '',
            validateRules: [
              {
                required: true,
                message: '${title}必选',
                handler: this.spaceIdChange,
              },
            ],
          },
          {
            title: '商品',
            key: 'goodsId',
            type: FormTypes.slot,
            width: '200px',
            placeholder: '请输入${title}',
            defaultValue: '',
            slotName: 'goodsIdSlot',
          },
          {
            title: '规格',
            key: 'goodsSpec',
            type: FormTypes.slot,
            width: '300px',
            placeholder: '请输入${title}',
            defaultValue: '',
            slotName: 'goodsSpecSlot',
          },
          {
            title: '报损数量',
            key: 'scrapNum',
            type: FormTypes.inputNumber,
            width: '120px',
            placeholder: '请输入${title}',
            defaultValue: '',
            validateRules: [
              {
                required: true,
                message: '${title}必填',
                handler: this.scrapNumChange,
              },
            ],
          },
          {
            title: '库存单位',
            key: 'unitId_dictText',
            width: '120px',
            defaultValue: '',
          },
          {
            title: '进货单价',
            key: 'price',
            // type: FormTypes.input,
            width: '120px',
            placeholder: '请输入${title}',
            defaultValue: '',
          },
          {
            title: '总价',
            key: 'totalPrice',
            width: '120px',
            placeholder: '请输入${title}',
            defaultValue: 0.0,
          },
        ],
      },
      url: {
        add: '/storage/stockScrapApproval/add',
        edit: '/storage/stockScrapApproval/edit',
        stockScrapApprovalDetail: {
          list: '/storage/stockScrapApproval/queryStockScrapApprovalDetailByMainId',
        },
      },
    }
  },
  computed: {
    formDisabled() {
      return this.disableSubmit
    },
  },
  watch: {
    /** 表单调整仓库选项赋值 */
    storeList: {
      handler(val) {
        if (val && !this.model.storeId) {
          this.$nextTick(() => {
            this.form.setFieldsValue({ storeId_dictText: val[0].store_name, storeId: val[0].id })
          })
          // 更新报损仓位列表
          this.getStoreSpacelist(val[0].id)
        }
      },
    },
    /** 主表报损总价 */
    tabledata: {
      deep: true,
      handler: function (n, o) {
        let t = 0
        let self = this
        Object.keys(n).forEach((key) => {
          const item = n[key]
          t += +item.totalPrice
        })
        self.$nextTick(() => {
          self.form.setFieldsValue({ totalPrice: (t || 0).toFixed(4) })
        })
      },
    },
  },
  methods: {
    getAllTable() {
      let values = this.tableKeys.map((key) => getRefPromise(this, key))
      return Promise.all(values)
    },
    /** 调用完edit()方法之后会自动调用此方法 */
    editAfter() {
      let self = this
      self.tabledata = {}
      if (self.storeList && self.storeList.length > 0) {
        self.model.storeId_dictText = self.model.storeId_dictText || self.storeList[0].store_name
        self.model.storeId = self.model.storeId || self.storeList[0].id
      }
      let fieldval = pick(self.model, 'scrapName', 'storeId_dictText', 'storeId', 'totalPrice', 'scrapReason', 'remark')

      self.$nextTick(() => {
        self.form.setFieldsValue(fieldval)
      })

      // 加载子表数据
      if (self.model.id) {
        let params = { id: self.model.id }
        // 更新报损仓位列表
        self.getStoreSpacelist(self.model.storeId)
        self.requestSubTableData(
          self.url.stockScrapApprovalDetail.list,
          params,
          self.stockScrapApprovalDetailTable,
          self.tabledataInit
        )
      }
    },
    /** 整理成formData */
    classifyIntoFormData(allValues) {
      let main = Object.assign(this.model, allValues.formValue)
      // 对goodsId goodsSpec 赋值
      let self = this
      Object.keys(self.tabledata).forEach((key) => {
        const items = allValues.tablesValue[0].values.filter((ite) => ite.id === key)
        items[0].goodsId = self.tabledata[key].goodsId
        items[0].goodsSpec = self.tabledata[key].goodsSpec
      })
      return {
        ...main, // 展开
        stockScrapApprovalDetailList: allValues.tablesValue[0].values,
      }
    },
    validateError(msg) {
      this.$message.error(msg)
    },
    popupCallback(row) {
      this.form.setFieldsValue(pick(row, 'storeId_dictText', 'storeId'))

      // 更新报损仓位列表
      this.getStoreSpacelist(row.storeId)
    },
    /** tabledata 初始化 */
    tabledataInit(res) {
      let self = this
      let {
        success,
        result: { records },
      } = res
      if (success) {
        records.forEach((item) => {
          const {
            id: rowId,
            spaceId,
            goodsId,
            goodsSpec,
            price,
            scrapNum,
            stockNum: maxScrapNum,
            totalPrice,
            goodsIdList = [],
            goodsSpecList = [],
          } = item
          self.$set(self.tabledata, rowId, {
            spaceId, // 报损仓位id
            goodsId, // 商品id
            goodsIdList, // 商品列表
            goodsSpec, // 规格id
            goodsSpecList, // 规格列表
            price, // 价格
            scrapNum, // 数量
            maxScrapNum, // 数量
            totalPrice, // 报损总价
          })

          // 获取商品列表和规格列表
          getQueryBySpaceId({ spaceId }).then((res) => {
            let { success, result } = res
            if (success) {
              self.tabledata[rowId].goodsIdList = result || []
            }
          })
          getQueryByGoodsId({
            goodsId,
            spaceId,
          }).then((res) => {
            let { success, result } = res
            if (success) {
              // self.tabledata[rowId].goodsSpecList = result || []
              self.$set(self.tabledata[rowId], 'goodsSpecList', result || [])
            }
          })
        })
      }
    },

    /**
     *  table 行操作
     */
    rowAdd({ row: { id: rowId }, target }) {
      let self = this
      self.$set(self.tabledata, rowId, {
        spaceId: '', // 报损仓位id
        goodsId: '', // 商品id
        goodsIdList: [], // 商品列表
        goodsSpec: '', // 规格id
        goodsSpecList: [], // 规格列表
        price: 0, // 价格
        scrapNum: 0, // 数量
        maxScrapNum: 0, // 数量
        totalPrice: 0, // 报损总价
      })

      target.setValues([
        {
          rowKey: rowId,
          values: {
            scrapNum: 0,
            price: 0,
            totalPrice: 0,
          },
        },
      ])
    },
    rowDel(delIds) {
      let self = this
      Object.keys(self.tabledata).forEach((key) => {
        self.$delete(self.tabledata, key)
      })
    },

    /**
     *  商品插槽区
     */

    /** 点击商品选择框获取报损仓位ID请求商品列表 */
    goodsIdFocus(props) {
      let self = this
      // 获取报损仓位下商品
      let { spaceId, goodsIdList } = self.tabledata[props.rowId]
      if (goodsIdList.length) return false
      getQueryBySpaceId({ spaceId }).then((res) => {
        let { success, result } = res
        if (success) {
          self.tabledata[props.rowId].goodsIdList = result || []
        }
      })
    },
    /** 获取商品ID */
    goodsIdChange(props, value) {
      let self = this

      Object.assign(self.tabledata[props.rowId], {
        goodsId: value || '',
        goodsSpec: '',
        goodsSpecList: [],
      })
      let { unitId_dictText } = self.tabledata[props.rowId].goodsIdList.find((item) => item.goodsId === value)

      props.target.setValues([
        {
          rowKey: props.rowId,
          values: {
            goodsId: value || '',
            goodsSpec: '', // 规格id
            price: 0, // 价格
            scrapNum: 0, // 数量
            maxScrapNum: 0, // 数量
            totalPrice: 0, // 报损总价
            unitId_dictText,
          },
        },
      ])
    },
    /** 搜索过滤 */
    goodsFilterOption(input, option) {
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },

    /**
     *  规格插槽区
     */

    /** 点击规格选择框获取商品ID请求规格列表 */
    goodsSpecFocus(props) {
      let self = this
      // 获取商品下规格
      let { goodsId, spaceId, goodsSpecList } = self.tabledata[props.rowId]

      if (goodsSpecList.length) return false
      getQueryByGoodsId({
        goodsId,
        spaceId,
      }).then((res) => {
        let { success, result } = res
        if (success) {
          // self.tabledata[props.rowId].goodsSpecList = result || []
          self.$set(self.tabledata[props.rowId], 'goodsSpecList', result || [])
        }
      })
    },
    /** 获取规格ID */
    goodsSpecChange(props, value) {
      let self = this
      let { spaceId, goodsId, goodsIdList, goodsSpecList } = self.tabledata[props.rowId]
      let goodsSpecListItem = goodsSpecList.find((item) => item.specsId === value)

      if (!goodsSpecListItem) {
        Object.assign(self.tabledata[props.rowId], {
          goodsSpec: '',
          price: 0,
          maxScrapNum: 0,
        })
        props.target.setValues([
          {
            rowKey: props.rowId,
            values: {
              goodsSpec: '',
              scrapNum: 0,
              price: 0,
              totalPrice: 0,
            },
          },
        ])
        return false
      }

      if (goodsSpecListItem) {
        Object.assign(self.tabledata[props.rowId], {
          goodsSpec: value,
          price: goodsSpecListItem.price,
          maxScrapNum: goodsSpecListItem.num,
        })
        props.target.setValues([
          {
            rowKey: props.rowId,
            values: {
              goodsSpec: value,
              scrapNum: 0,
              price: goodsSpecListItem.price,
              totalPrice: 0,
            },
          },
        ])
      }
    },
    /** 搜索过滤 */
    goodsFilterOption(input, option) {
      return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
    },

    /**
     *  api请求区域 ======================================================
     */

    /** 请求报损仓位列表 */
    getStoreSpacelist(id) {
      let self = this
      let rowId = id || null
      if (!!!rowId) return false
      return getStockPosition({ id: rowId }).then((res) => {
        if (res.success) {
          let arr = []
          res.result.records.forEach((ite) => {
            let obj = {
              title: ite.spaceCode,
              text: ite.spaceCode,
              value: ite.id,
            }
            arr.push(obj)
          })
          self.$set(self.stockScrapApprovalDetailTable.columns[0], 'options', arr)
        }
      })
    },
    /** 审批 */
    handleApp(val) {
      let self = this
      self.confirmLoading = true
      postStockScrapApproval({ status: val, id: self.model.id, remark: self.form.getFieldValue('remark') })
        .then((res) => {
          if (res.success) {
            self.$message.success(res.message)
            self.$emit('ok')
            self.close()
          } else {
            self.$message.warning(res.message)
          }
        })
        .finally(() => {
          self.confirmLoading = false
        })
    },

    /**
     *  子表校验区域 ======================================================
     */

    /** 当选择报损仓位时获取商品信息 */
    spaceIdChange(type, value, row, column, callback, target) {
      let self = this
      if (type === 'change') {
        // 获取报损仓位下商品
        Object.assign(self.tabledata[row.id], {
          spaceId: value, // 报损仓位id
          goodsIdList: [], // 商品列表
          goodsSpecList: [], // 规格列表
        })
        target.setValues([
          {
            rowKey: row.id,
            values: {
              goodsId: '', // 商品id
              goodsSpec: '', // 规格id
              price: 0, // 价格
              scrapNum: 0, // 数量
              totalPrice: 0, // 报损总价
            },
          },
        ])
      }
      callback()
    },
    /** 校验输入的报损数量大小 */
    scrapNumChange(type, value, row, column, callback, target) {
      let self = this
      if (type === 'blur') {
        let tableItem = self.tabledata[row.id]


        if (isNaN(value)) {
          return callback(false, '请输入数字')
        }
        if (+value > tableItem.maxScrapNum) {
          return callback(false, '报损数量不可大于库存数量')
        }
        if (+(value.toString()).split('.').length > 1 && +(value.toString()).split('.')[1].length > 4) {
          return callback(false, '报损数量只精确到4位小数')
        }

        if (value < 0) {
          return callback(false, '不可为负数')
        }

        let totalPrice = (+value * (tableItem.price || 0)).toFixed(4)
        tableItem.totalPrice = totalPrice
        target.setValues([
          {
            rowKey: row.id,
            values: {
              scrapNum: parseFloat(value).toFixed(4),
              totalPrice,
            },
          },
        ])
        return callback(true)
      } else {
        return callback()
      }
    },
    valIsNaN(value) {
      return typeof value === 'number' && !isNaN(value);
    }
  },
}
</script>

<style scoped>
</style>